package com.golxen.framework.user.dao;


import com.golxen.framework.common.BuiltinPlugin;
import com.golxen.framework.db.DBManager;
import com.golxen.framework.db.dao.AbstractDaoImplByEntity;
import com.golxen.framework.user.dao.entity.UserInfo;
import com.mysql.cj.util.StringUtils;

import java.math.BigInteger;
import java.sql.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class UserDaoImpl extends AbstractDaoImplByEntity<UserInfo> {


    public Map<Long, UserInfo> getUserInfoMap() {
        String sql = "select * from t_u_user";
        ResultSet rs = null;
        CallableStatement call = null;
        Map<Long, UserInfo> dataMap = new ConcurrentHashMap<>();
        try {
            getDb().setConnName(DBManager.userDbName);
            call = getDb().getConnection().prepareCall(sql);
            rs = call.executeQuery();
            while (rs.next()) {
                UserInfo userInfo = parse(rs);
                dataMap.put(userInfo.getUserId(), userInfo);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            getDb().closeConnection(call, rs);
        }
        return dataMap;
    }

    public UserInfo getUserInfoByUserId(long userId) {
        String sql = "select * from t_u_user where userId=?";
        ResultSet rs = null;
        CallableStatement call = null;
        try {
            getDb().setConnName(DBManager.userDbName);
            call = getDb().getConnection().prepareCall(sql);
            call.setLong(1, userId);
            rs = call.executeQuery();
            while (rs.next()) {
                UserInfo userInfo = parse(rs);
                return userInfo;
            }
        } catch (Exception e) {
            logger.error(Thread.currentThread().getStackTrace()[1].getMethodName() + ":", e);
        } finally {
            getDb().closeConnection(call, rs);
        }
        return null;
    }


    public UserInfo register(long userId) {
        String sql = "INSERT INTO t_u_user(registerTime,lastLoginTime,nickName,"
                + "userId) VALUES(?,?,?,?,?,?)";
        PreparedStatement call = null;
        UserInfo info;
        try {
            getDb().setConnName(DBManager.userDbName);
            call = getDb().getConnection().prepareStatement(sql);
            long nowTime = System.currentTimeMillis() / 1000;
            int i = 1;
            call.setLong(i++, nowTime);
            call.setLong(i++, 0);
            call.setString(i++, "");
            call.setLong(i++, userId);
            call.setLong(i++, BuiltinPlugin.getServerId());
            if (call.executeUpdate() > 0) {
                info = new UserInfo();
                info.setUserId(userId);
                return info;
            }
        } catch (Exception e) {
            logger.error(Thread.currentThread().getStackTrace()[1].getMethodName() + ":", e);
        } finally {
            getDb().closeConnection(call, null);
        }
        return null;
    }

    public boolean isSameNickName(String nickName) {
        String sql = "select * from t_u_user where nickName=?";
        ResultSet rs = null;
        CallableStatement call = null;
        try {
            getDb().setConnName(DBManager.userDbName);
            call = getDb().getConnection().prepareCall(sql);
            call.setString(1, nickName);
            rs = call.executeQuery();
            while (rs.next()) {
                return true;
            }
        } catch (Exception e) {
            logger.error(Thread.currentThread().getStackTrace()[1].getMethodName() + ":", e);
        } finally {
            getDb().closeConnection(call, rs);
        }
        return false;
    }

    public boolean updateNickName(long userId, String nickName) {
        String sql = "UPDATE t_u_user SET nickName=? WHERE userId=?";
        try {
            getDb().setConnName(DBManager.userDbName);
            Map<Integer, Object> para = new HashMap<>();
            int i = 1;
            para.put(i++, nickName);
            para.put(i++, userId);
            return getDb().executeBatchQuery(sql, Collections.singletonList(para)) > -1;
        } catch (Exception e) {
            logger.error(Thread.currentThread().getStackTrace()[1].getMethodName() + ":", e);
        }
        return false;
    }



    public long getMaxUserId() {
        String sql = "select ifnull(max(userId),0) as maxId from t_u_user";
        ResultSet rs = null;
        CallableStatement call = null;
        long maxId = 0;
        try {
            getDb().setConnName(DBManager.userDbName);
            call = getDb().getConnection().prepareCall(sql);
            rs = call.executeQuery();
            while (rs.next()) {
                maxId = rs.getLong("maxId");
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            getDb().closeConnection(call, rs);
        }
        return maxId;
    }



    @Override
    protected boolean addData(UserInfo data) {
        return false;
    }

    @Override
    protected boolean updateData(UserInfo data) {
        PreparedStatement call = null;
        String sql = "UPDATE t_u_user SET nickName=?,registerTime=?,lastLoginTime=?"
                + " WHERE userId=?";
        try {
            getDb().setConnName(DBManager.userDbName);
            call = getDb().getConnection().prepareStatement(sql);
            int i = 1;
            call.setString(i++, data.getNickName());
            call.setLong(i++, data.getRegisterTime());
            call.setLong(i++, data.getLastLoginTime());
            call.setLong(i++, data.getUserId());
            return call.executeUpdate() > 0;
        } catch (Exception e) {
            logger.error(Thread.currentThread().getStackTrace()[1].getMethodName() + ":", e);
        } finally {
            getDb().closeConnection(call, null);
        }
        return false;
    }

    @Override
    protected UserInfo parseData(ResultSet rs) throws SQLException {
        UserInfo data = new UserInfo();
        data.setUserId(rs.getLong("userId"));
        data.setNickName(rs.getString("nickName") == null ? "" : rs.getString("nickName"));
        data.setRegisterTime(rs.getLong("registerTime"));
        data.setLastLoginTime(rs.getLong("lastLoginTime"));

        return data;
    }

    public boolean checkSqlConnectionStatus() {
        ResultSet rs = null;
        CallableStatement call = null;
        String sql = "select userId from t_u_user limit 1";
        try {
            getDb().setConnName(DBManager.userDbName);
            call = getDb().getConnection().prepareCall(sql);
            rs = call.executeQuery();
        } catch (Exception e) {
            logger.error(Thread.currentThread().getStackTrace()[1].getMethodName() + ":", e);
            return false;
        } finally {
            getDb().closeConnection(call, rs);
        }
        return true;
    }


}
